package com.foo.common.base.utils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import com.foo.example.util.Game;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class FooUtils {

	public static void log(Object message) {
		System.out.println(message);
	}

	public static String parseMagnetStr(String source) {
		int magnetProtocolLength = 60;

		int x = source.indexOf("magnet:?xt=", 0);

		if (x == -1) {
			System.out.print("No magnet exist，reutrn");
			return "";
		}
		return source.substring(x, x + magnetProtocolLength);

	}

	/**
	 * 转化为年到秒的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Second(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 转化为年到秒的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Second(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
				.parseDateTime(date).toDate();
	}

	/**
	 * 转化为年到天的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Day(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd");
	}

	/**
	 * 转化为年到天的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Day(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(date)
				.toDate();
	}

	/**
	 * 转化为年到分钟的时间格式
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String toDateFromYear2Minute(DateTime dateTime) {
		return dateTime.toString("yyyy-MM-dd HH:mm");
	}

	/**
	 * 转化为年到分钟的时间格式
	 * 
	 * @param date
	 * @return
	 */
	public static Date toDateFromYear2Minute(String date) {
		return DateTimeFormat.forPattern("yyyy-MM-dd HH:mm")
				.parseDateTime(date).toDate();
	}

	/**
	 * 读入HttpServletResponse,输出失败的Json字符串到前台,全浏览器兼容
	 * 
	 * @param response
	 * @throws IOException
	 */
	public static void printJsonSuccessMsg(HttpServletResponse response)
			throws IOException {
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		response.getWriter().write(
				new Gson().toJson(new ImmutableMap.Builder<String, String>()
						.put("success", "true").put("msg", "ok").build()));
	}

	public static void printJsonMessage(HttpServletResponse response,
			String message) throws IOException {
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		response.getWriter().write(
				new Gson().toJson(new ImmutableMap.Builder<String, String>()
						.put("success", "true").put("msg", "ok")
						.put("message", message).build()));
	}

	/**
	 * 读入HttpServletResponse,将Json格式写出对象到HttpServletResponse
	 * 
	 * 只传一个参数将直接把对象写出到HttpServletResponse，
	 * 传二个参数则会把对象以键值对的方式写出到HttpServletResponse，
	 * 
	 * @param response
	 * @param object
	 *            ,可变参数，限制于2个参数之内
	 * @throws IOException
	 */
	public static void printJsonObject(HttpServletResponse response,
			Object... object) throws IOException {
		boolean myObjectLength = object.length >= 1 && object.length <= 2;
		Preconditions.checkArgument(myObjectLength,
				"Object Length should be between 1 and 2");
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		response.setContentType("text/plain");
		Map<String, Object> myResultMap = Maps.newHashMap();
		myResultMap.put("success", "true");
		myResultMap.put("msg", "ok");
		if (object.length == 2) {
			myResultMap.put(object[0].toString(), object[1]);
			response.getWriter().write(new Gson().toJson(myResultMap));
		} else {
			response.getWriter().write(new Gson().toJson(object[0]));
		}
	}

	/**
	 * 
	 * 读入HttpServletResponse,将Json格式写出对象到HttpServletResponse 此方法能够序列化null字段
	 * 只传一个参数将直接把对象写出到HttpServletResponse
	 * ，传二个参数则会把对象以键值对的方式写出到HttpServletResponse，
	 * 
	 * @author Liuchang
	 * @since Dec,2011
	 * 
	 * @param response
	 * @param object
	 *            ,可变参数，限制于2个参数之内
	 * @throws IOException
	 */
	public static void printJsonObjectSerializeNulls(
			HttpServletResponse response, Object... object) throws IOException {
		boolean myObjectLength = object.length >= 1 && object.length <= 2;
		Preconditions.checkArgument(myObjectLength,
				"Object Length should be between 1 and 2");
		response.setCharacterEncoding(Charsets.UTF_8.toString());
		Map<String, Object> myResultMap = Maps.newHashMap();
		response.setContentType("text/plain");
		myResultMap.put("success", "true");
		myResultMap.put("msg", "ok");
		// serializeNulls 序列化null字段
		Gson gson = new GsonBuilder().serializeNulls()
				.excludeFieldsWithoutExposeAnnotation().create();
		if (object.length == 2) {
			myResultMap.put(object[0].toString(), object[1]);
			response.getWriter().write(gson.toJson(myResultMap));
		} else {
			response.getWriter().write(gson.toJson(object[0]));
		}
	}

	/**
	 * 如果列表不为空，那么返回列表本身；如果列表为空，则返回空列表
	 */
	public static <T> List<T> nullToEmpty(List<T> list) {
		if (list != null && list.size() > 0) {
			return list;
		} else {
			return Lists.newArrayList();
		}
	}

	public static String formatDouble(String result) {
		return String.format("%1$.2f", Double.parseDouble(result));
	}

	public static String formatDouble(double result) {
		return String.format("%1$.2f", result);
	}

	/**
	 * 判定是否是数字
	 * 
	 * @param code
	 *            例如：12.23
	 * @return
	 */
	public static boolean isNum(String code) {
		Pattern pattern = Pattern.compile("\\d+(\\.\\d+)?");
		Matcher isNum = pattern.matcher(code);
		return isNum.matches();
	}

	/**
	 * 判断是否是字符
	 * 
	 * @param code
	 * @return
	 */
	public static boolean isCharacter(String code) {
		Pattern pattern = Pattern.compile("[A-Za-z]*");
		Matcher isNum = pattern.matcher(code);
		return isNum.matches();
	}

	public static String generateUUID() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 格式化100000为100,000样式的字符串
	 * 
	 * @param number
	 * @return
	 */
	public static String getDecimalFormat(long number) {
		DecimalFormat dec = new DecimalFormat();
		dec.setGroupingUsed(true);
		dec.setGroupingSize(3);
		return dec.format(number);
	}

	/**
	 * 得到c不匹配周模式的ron表达式，例如56 20 11 26 7 ? 2013
	 * 
	 * @param myDateTime
	 * @return
	 */
	public static String getCronExpressionFromDateTime(DateTime myDateTime) {
		return "" + myDateTime.getSecondOfMinute() + " "
				+ myDateTime.getMinuteOfHour() + " "
				+ myDateTime.getHourOfDay() + " " + myDateTime.getDayOfMonth()
				+ " " + myDateTime.getMonthOfYear() + " ? "
				+ myDateTime.getYear() + "";
	}

	/**
	 * 得到oracle方言的时间查询片段，例如<br>
	 * <code>TO_DATE('2013-07-26 11:24:50','YYYY-MM-DD HH24:MI:SS')</code>
	 * 
	 * @param dateTime
	 * @return
	 */
	public static String getOracleSearchFragment(DateTime dateTime) {
		return "TO_DATE('" + FooUtils.toDateFromYear2Second(dateTime)
				+ "','YYYY-MM-DD HH24:MI:SS')";
	}

	/**
	 * Used in debug a business model
	 * 
	 * @param object
	 * @return
	 * @throws IntrospectionException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static String reflectToString(Object object)
			throws IntrospectionException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException {
		Preconditions.checkNotNull(object);

		StringBuilder sb = new StringBuilder();
		sb.append(object.getClass().getName()).append("[");
		for (Field field : Game.class.getDeclaredFields()) {
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(),
					Game.class);
			Method method = pd.getReadMethod();
			sb.append(field.getName());
			sb.append("=");
			sb.append(method.invoke(object) == null ? "<null>" : method.invoke(
					object).toString());
			sb.append(",");
		}
		String result = sb.substring(0, sb.length() - 1) + "]";
		return result;
	}

	public static void main(String[] args) {
		ToStringBuilder.reflectionToString(FooUtils.class);
		System.out.println("fffffff");
	}

	public static void main1(String[] args) {

		// System.out.println(new Date().getTime());
		//
		// for (int i = 0; i < 10; i++) {
		// System.out.println(getRandomUUID());
		// }
		//
		// String s = "\u7535\u4fe1\u5341\u56db";
		//
		// System.out.println(new String(s.getBytes("utf-8")));
		//
		// ClassPathResource myPath2 = new ClassPathResource(
		// "json/chrome-har.json");
		// String myString = IOUtils.toString(myPath2.getInputStream(),
		// "UTF-8");
		// System.out.println(myString);

		// 从excel解析数据,Start
		String myFileDirectory = "d:\\/tmp/";
		// String myResultFileName = "d:\\华为平台数据整理.xlsx";
		File myDirectory = new File(myFileDirectory);
		// File myFile = null;
		for (File file : myDirectory.listFiles()) {
			// System.out.println("Encounting file name of" + file.getName());
			if (file.isDirectory()) {
				System.out.println("Encounting directory name of"
						+ file.getName());
				continue;
			}
			try {
				OPCPackage pkg = OPCPackage.open(new File(myFileDirectory
						+ file.getName()));
				XSSFWorkbook wb = new XSSFWorkbook(pkg);
				// XSSFWorkbook wb = new XSSFWorkbook();

				// System.out
				// .println("Start deal with excel of:" + file.getName());
				System.out.println(wb.getNumberOfSheets());
				for (int mySheet = 0; mySheet < wb.getNumberOfSheets(); mySheet++) {

					Sheet sheet = wb.getSheetAt(mySheet);
					// 第一行为标题栏，跳过
				}// 结束所有工作表的读取
				pkg.close();
				System.out.println("End deal with file name of:"
						+ file.getName());
			} catch (Exception e) {
				System.out.println("There's problem with file name of:"
						+ file.getName());
				// e.printStackTrace();
			} finally {
			}
		}
	}
}
